package  
{
	import flash.display.BitmapData;
	import flash.filters.BlurFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import org.flixel.*;
	/**
	 * ...
	 * @author morgan
	 */
	public class GameState extends FlxState
	{
		[Embed (source = "../data/swarmglow.png")] private var glowImg:Class;
		[Embed (source = "../data/cursor.png")] private var cursorImg:Class;
		[Embed (source = "../data/cursor2.png")] private var cursor2Img:Class;
		[Embed (source = "../data/s5.png")] private var screenForegroundImg:Class;
		[Embed (source = "../data/s5_p25.png")] private var screenPara25Img:Class;
		[Embed (source = "../data/s5_p50.png")] private var screenPara50Img:Class;
		
		[Embed (source = "../data/vignette.png")] private var vignetteImg:Class;
		
		public var bugGroup:FlxGroup = new FlxGroup();
		public var glowGroup:FlxGroup = new FlxGroup();
		public var humanGroup:FlxGroup = new FlxGroup();
		public var swarmGlow:FlxSprite;
		public var glowright:FlxSprite;
		public var vignette:FlxSprite;
		
		public var map:FlxSprite;
		public var entities:FlxGroup = new FlxGroup();
		
		public var bugTarget:FlxPoint = new FlxPoint(0, 0);
		public var bugTargetObj:Entity; 
		
		public var time:Number = 0;
		public var waveyness:Number = 0;
		public var bloom:Number = 0;
		
		public var human:Human;
		
		public var targetScroll:int;
		
		public function GameState() 
		{
			FlxG.mouse.show(cursorImg, 2, -17, -17);
			super();
		}
		
		override public function create():void 
		{
			super.create();
			FlxG.bgColor = 0xff555555;
			for (var i:int = 0; i < 0; i++)
			{
				bugGroup.add(new Bug(Math.random() * 5 + 100, Math.random() * 5 + 80, bugGroup));
			}
			
			swarmGlow = new FlxSprite(0, 0, glowImg);
			swarmGlow.alpha = 0.25;
			swarmGlow.blend = "overlay";
			glowGroup.add(swarmGlow);
			
			var para25:FlxSprite = new FlxSprite(0, 0, screenPara25Img);
			var para50:FlxSprite = new FlxSprite(0, 0, screenPara50Img);
			map = new FlxSprite(0, 0, screenForegroundImg);
			para25.scrollFactor.x = 0.25;
			para50.scrollFactor.x = 0.50;
			
			human = new Human(55, 200);
			humanGroup.add(human);
			
			vignette = new FlxSprite(0, 0, vignetteImg);
			vignette.scrollFactor.x = vignette.scrollFactor.y = 0;
			vignette.alpha = 1.0;
			
			var dialog:Dialog = new Dialog();
			dialog.addMessage("This is a test of the automated dialog boxing system. This is a long thing of text which will hopefully word wrap.")
			dialog.addMessage("what be up?");
			
			var grass:Grass = new Grass(map);
			grass.generateGrass();
			
			add(para25);
			add(para50);
			add(glowGroup);
			add(map);
			add(entities);
			add(bugGroup);
			add(humanGroup);
			add(grass);
			add(dialog);
			add(dialog.text);
			add(vignette);
		}
		
		public function updateBugs():FlxPoint
		{
			if (bugTargetObj == null)
			{
				bugTarget = new FlxPoint(FlxG.mouse.x, FlxG.mouse.y);
			}
			else
			{
				bugTarget = new FlxPoint(bugTargetObj.x + bugTargetObj.width / 2, bugTargetObj.y + bugTargetObj.height / 2);
			}
			
			// Randomize the bug array. This is useful because the bugs have a limit of
			// how many bugs they consider for flocking behavior. If the array always has
			// the same order, weird groups form because they always look at the same set.
			var l:int = bugGroup.length;
			for (var i:int = 0; i < l; i++)
			{
				var temp:Bug = bugGroup.members[i];
				var rnd:int = int(Math.random() * l);
				bugGroup.members[i] = bugGroup.members[rnd];
				bugGroup.members[rnd] = temp;
			}
			var midx:int = 0;
			var midy:int = 0;
			for each(var b:Bug in bugGroup.members)
			{
				// Make a list of all things to test collision against.
				
				// copy.
				var collidable:Array = entities.members.slice(0, entities.length);
				collidable.push(map);
				var bugLocValid:Boolean = true;
				for each (var obj:FlxSprite in collidable)
				{
					// Check if colliding.
					if (obj.pixelsOverlapPoint(new FlxPoint(b.x+1, b.y+1), 0x00))
					{
						if (obj is Entity)
						{
							(obj as Entity).bugInfluence += 1;
						}
						// Jump to the last known valid location if there's a collision.
						b.x = b.lastValid.x;
						b.y = b.lastValid.y;
						// Bugs get really stuck on silly pixels, so give some random velocity.
						b.velocity.x = Math.random() * 100 - 50;
						b.velocity.y = Math.random() * 100 - 50;
						bugLocValid = false;
					}
				}
				if (bugLocValid)
				{
					b.lastValid.x = b.x;
					b.lastValid.y = b.y;				
				}
				
				// Finding the avg swarm position while we're in this loop
				midx += b.x;
				midy += b.y;
			}
			midx /= bugGroup.length;
			midy /= bugGroup.length;
			// Place the glow there.
			swarmGlow.x = midx - swarmGlow.width / 2;
			swarmGlow.y = midy - swarmGlow.height / 2;
			
			return new FlxPoint(midx, midy);
		}
		
		override public function update():void 
		{
			super.update();
			time += FlxG.elapsed;
			
			if (bugGroup.members.length > 0)
			{
				// Scroll towards the midpoint of the bugs.
				var mid:FlxPoint = updateBugs();
				var co:Number = 0.02;
				var tx:Number = (mid.x - FlxG.width / 2) * co + FlxG.camera.scroll.x * (1 - co);				
				if (Math.abs(tx - FlxG.camera.scroll.x) > 0.5)
				{
					FlxG.camera.scroll.x = Math.min(Math.max(0, tx), map.width - FlxG.width);
				}
				FlxG.mouse.show(cursorImg,2, -17, -17);
			}
			else
			{
				if (human.x <= 220) { targetScroll = 0; }
				else if (human.x <= 380) { targetScroll = 160; }
				else { targetScroll = 320; }
				if (FlxG.camera.scroll.x > targetScroll)
				{
					FlxG.camera.scroll.x = Math.max(FlxG.camera.scroll.x - 5, targetScroll);
					FlxG.timeScale = 0.1;
				}
				else if (FlxG.camera.scroll.x < targetScroll)
				{
					FlxG.camera.scroll.x = Math.min(FlxG.camera.scroll.x + 5, targetScroll);
					FlxG.timeScale = 0.1;
				}
				else
				{
					FlxG.timeScale = 1.0;
				}
				FlxG.mouse.load(cursor2Img,2, -17, -17);
			}
			/*
			if (bloom > 0.5)
			{
				waveyness = (FlxG.height - mid.y) / (FlxG.height / 6);
			}
			*/
			//bloom = 1.0
			if (bugGroup.members.length > 0)
			{
				bloom = 1.0;
				vignette.alpha = Math.max(vignette.alpha - FlxG.elapsed, 0.0);
			}
			else
			{
				bloom = 0.0;
				vignette.alpha = Math.min(vignette.alpha + FlxG.elapsed, 1.0);
			}
			
		}
		
		override public function draw():void 
		{
			super.draw();

			if (waveyness >= 0)
			{
				// left-right distortion on a sine wave
				for (var y:int = 0; y < FlxG.height; ++y)
				{
					var offx:Number = Math.sin(y / 5 + time * 2) * waveyness;
					FlxG.camera.buffer.copyPixels(FlxG.camera.buffer, new Rectangle(0, y, FlxG.width, 1), new Point(offx, y));
				}
				// vertical
				for (var x:int = 0; x < FlxG.width; ++x)
				{
					var offy:Number = Math.sin(x / 20 + time * 4) * waveyness / 3;
					FlxG.camera.buffer.copyPixels(FlxG.camera.buffer, new Rectangle(x, 0, 1, FlxG.height), new Point(x, offy));
				}
			}
			
			if (bloom > 0)
			{
				// do a bloom by blurring the image and then overlaying that on itself.
				var blur:BlurFilter = new BlurFilter();
				blur.blurX = 5;
				blur.blurY = 5;
				blur.quality = 2;
				var result:BitmapData = new BitmapData(FlxG.width, FlxG.height);
				result.applyFilter(FlxG.camera.buffer,
					new Rectangle(0, 0, FlxG.width, FlxG.height),
					new Point(0, 0), blur);
					
				// distort the blurry img with sine wave
				for (y = 0; y < FlxG.height; ++y)
				{
					offx = Math.sin(y / 4 + time * 5) * 2;
					result.copyPixels(result, new Rectangle(0, y, FlxG.width, 1), new Point(offx, y));
				}
				// vertical
				for (x = 0; x < FlxG.width; ++x)
				{
					offy = Math.sin(x / 17 + time * 3) * 2;
					result.copyPixels(result, new Rectangle(x, 0, 1, FlxG.height), new Point(x, offy));
				}				
				FlxG.camera.buffer.draw(result, null, new ColorTransform(1, 1, 1, 0.4, 0, 0, 0, 0));
				FlxG.camera.buffer.draw(result, null, new ColorTransform(1, 1, 1, 0.5, 0, 0, 0, 0), "overlay");
			}
		}
	}

}